package com.skyjing.askit

import android.app.DownloadManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.Uri
import android.os.Build
import android.os.Environment
import java.io.File
import java.util.*

/**
 * 使用系统下载器downloadmanager下载文件
 * 指定路径需要全路径，且需要申请动态权限
 */
class AsDownloadManagerUitls @JvmOverloads constructor(
    private val mContext: Context
    , private val url: String
    , private val savePath: String = ""
    , private val name: String = getFileNameByUrl(
        url
    )
    , private val saveFileType: String = Environment.DIRECTORY_DOWNLOADS
) {
    private var downloadManager: DownloadManager
    private var downloadId: Long = 0
    private var path: String? = null
    private var listener: ListenerImpl? = null
    private lateinit var timer: Timer
    private lateinit var task: TimerTask
    private var refreshTime = 500L
    private var request: DownloadManager.Request = DownloadManager.Request(Uri.parse(url))

    init {
        //设置下载的路径
        //该路径为 /storage/emulated/0/Android/data/com.skyjing.astools/files/Download/C10B2237586138DF3909E47B981B73F9.apk
//        val file = File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), name)

        val file = if (savePath.isEmpty()) {
//            File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), name)
            File(mContext.getExternalFilesDir(saveFileType), name)
        } else {
            File(savePath, name)
        }
        request.apply {
            setTitle(name)
            setDescription("文件正在下载中......")
            setDestinationUri(Uri.fromFile(file))
        }
        path = file.absolutePath
        downloadManager = mContext.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
    }

    fun setListener(listener: ListenerImpl?): AsDownloadManagerUitls {
        this.listener = listener
        return this
    }

    fun setListener(listener: ListenerImpl.() -> Unit): AsDownloadManagerUitls {
        val temp = ListenerImpl().apply(listener)
        this.listener = temp
        return this
    }

    fun setTitle(title: String?): AsDownloadManagerUitls {
        request.setTitle(title)
        return this
    }

    fun setDescription(des: String?): AsDownloadManagerUitls {
        request.setDescription(des)
        return this
    }

    //表示允许MediaScanner扫描到这个文件，默认不允许。
    fun mediaScanner(): AsDownloadManagerUitls {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
            request.allowScanningByMediaScanner()
        }
        return this
    }

    fun addRequestHeader(
        header: String?,
        value: String?
    ): AsDownloadManagerUitls {
        request.addRequestHeader(header, value)
        return this
    }

    fun setMimeType(type: String?): AsDownloadManagerUitls {
        request.setMimeType(type)
        return this
    }

    fun setNotificationVisibility(type: Int): AsDownloadManagerUitls {
        request.setNotificationVisibility(type)
        return this
    }

    fun setAllowedOverRoaming(isAllOwed: Boolean): AsDownloadManagerUitls {
        request.setAllowedOverRoaming(isAllOwed)
        return this
    }

    //显示在下载界面，即下载后的文件在系统下载管理里显示
    fun setVisibleInDownloadsUi(isShow: Boolean): AsDownloadManagerUitls {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
            request.setVisibleInDownloadsUi(isShow)
        }
        return this
    }

    fun setAllowedNetworkTypes(type: Int): AsDownloadManagerUitls {
        request.setAllowedNetworkTypes(type)
        return this
    }

    fun setRefreshTime(time: Long): AsDownloadManagerUitls {
        refreshTime = time
        return this
    }

    /**
     * 开始下载
     */
    fun download() {
        if (downloadManager != null) {
            listener?.onPrepare()
            downloadId = downloadManager.enqueue(request)

            //监听下载进度
            val query = DownloadManager.Query()
            timer = Timer()
            task = object : TimerTask() {
                override fun run() {
                    val cursor = downloadManager.query(query.setFilterById(downloadId))
                    if (cursor != null && cursor.moveToFirst()) {
                        if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))
                            == DownloadManager.STATUS_SUCCESSFUL
                        ) {
//                        if (listener != null) {
//                            listener.onDownloadPercent();
//                        }
                            cancleTask()
                        }
                        val title =
                            cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_TITLE))
                        val address =
                            cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI))
                        val currentSize =
                            cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR))
                        val totalSize =
                            cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES))
//                        val pro = (currentSize * 100 / totalSize).toInt()
//                        LogUtils.e("DownloadManagerUitls", " tatal:${String.format("%.2fm", (totalSize / 1000f / 1000f))} ")
//                        "下载进度：${String.format("%.2f", pro)}%"
                        val pro = (currentSize * 100f / totalSize)
                        if (totalSize > 0) {
                            listener?.onDownloadPercent(totalSize, currentSize)
                        }
                        cursor.close()
                    }
                }
            }
            //500毫秒查询一次
            timer.schedule(task, 0, refreshTime)
            task.run()
        }

        //注册广播接收者，监听下载状态
        mContext.registerReceiver(receiver, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))
    }

    private fun download2() {
        val request = DownloadManager.Request(Uri.parse(url))
        request.apply {
            //添加请求头
//            addRequestHeader(String header, String value)
            //在通知栏中显示，默认就是显示的,不设置，下载完成后就不会在通知栏显示提示
//            setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
            setTitle(name)
            setDescription("文件正在下载中......")
            /**
             * 这是安卓.apk文件的类型。有些机型必须设置此方法，才能在下载完成后，
             * 点击通知栏的Notification时，才能正确的打开安装界面。
             * 不然会弹出一个Toast（can not open file）.其他文件类型的MimeType
             */
//                setMimeType("application/vnd.android.package-archive")
//            allowScanningByMediaScanner();//表示允许MediaScanner扫描到这个文件，默认不允许。
            /**
             * 表示下载允许的网络类型，默认在任何网络下都允许下载。
             * 有NETWORK_MOBILE、NETWORK_WIFI、NETWORK_BLUETOOTH三种及其组合可供选择。如果只允许wifi下载，而当前网络为3g，则下载会等待。
             * request.setAllowedOverRoaming(boolean allow)移动网络情况下是否允许漫游。
             */
//            setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI)
            //用于设置漫游状态下是否可以下载
//            setAllowedOverRoaming(false)
        }

        //设置下载的路径
        //该路径为 /storage/emulated/0/Android/data/com.skyjing.astools/files/Download/C10B2237586138DF3909E47B981B73F9.apk
        val file = File(mContext.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), name)
        request.setDestinationUri(Uri.fromFile(file))
        path = file.absolutePath
        //获取DownloadManager
        if (downloadManager == null) {
            downloadManager = mContext.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
        }
        //将下载请求加入下载队列，加入下载队列后会给该任务返回一个long型的id，通过该id可以取消任务，重启任务、获取下载的文件等等
        if (downloadManager != null) {
            listener?.onPrepare()
            downloadId = downloadManager!!.enqueue(request)

            //监听下载进度
            val query = DownloadManager.Query()
            timer = Timer()
            task = object : TimerTask() {
                override fun run() {
                    val cursor = downloadManager!!.query(query.setFilterById(downloadId))
                    if (cursor != null && cursor.moveToFirst()) {
                        if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))
                            == DownloadManager.STATUS_SUCCESSFUL
                        ) {
//                        if (listener != null) {
//                            listener.onDownloadPercent();
//                        }
                            cancleTask()
                        }
                        val title =
                            cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_TITLE))
                        val address =
                            cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI))
                        val currentSize =
                            cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR))
                        val totalSize =
                            cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES))
//                        val pro = (currentSize * 100 / totalSize).toInt()
//                        LogUtils.e("DownloadManagerUitls", " tatal:${String.format("%.2fm", (totalSize / 1000f / 1000f))} ")
//                        "下载进度：${String.format("%.2f", pro)}%"
                        val pro = (currentSize * 100f / totalSize)
                        if (pro > 0) {
                            listener?.onDownloadPercent(totalSize, currentSize)
                        }
                        cursor.close()
                    }
                }
            }
            //500毫秒查询一次
            timer.schedule(task, 0, 500)
            task.run()
        }
        //注册广播接收者，监听下载状态
        mContext.registerReceiver(receiver, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))
    }

    fun cancle() {
        mContext.unregisterReceiver(receiver)
        //判断是否已经初始化
        cancleTask()
        downloadManager.remove(downloadId)
    }

    private fun cancleTask() {
        if (this::task.isInitialized)
            task.cancel()
    }

    //广播监听下载的各个状态
    private val receiver: BroadcastReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            val query = DownloadManager.Query()
            //通过下载的id查找
            query.setFilterById(downloadId)
            if (downloadManager != null) {
                val cursor = downloadManager.query(query)
                if (cursor != null) {
                    if (cursor.moveToFirst()) {
                        when (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))) {
                            DownloadManager.STATUS_PAUSED -> {
                            }
                            DownloadManager.STATUS_PENDING -> {
                            }
                            DownloadManager.STATUS_RUNNING -> {
                            }
                            DownloadManager.STATUS_SUCCESSFUL -> {
                                cancleTask()
                                val title =
                                    cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_TITLE))
                                val address =
                                    cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI))
                                val currentSize =
                                    cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR))
                                val totalSize =
                                    cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES))
//                            val pro = (totalSize * 100 / currentSize).toInt()
                                val pro = (currentSize * 100f / totalSize)
                                if (pro > 0) {
                                    listener?.onDownloadPercent(totalSize, currentSize)
                                }
                                listener?.onSuccess(path)
                                cursor.close()
                                mContext.unregisterReceiver(this)
                            }
                            DownloadManager.STATUS_FAILED -> {
                                listener?.onFailed(Exception("下载失败"))
                                cancleTask()
                                cursor.close()
                                mContext.unregisterReceiver(this)
                            }
                        }
                    }
                }
            }
        }
    }

    interface DownloadManagerUitlsListener {
        fun onPrepare()
        fun onSuccess(path: String?)
        fun onFailed(throwable: Throwable?)
        fun onDownloadPercent(totalSize: Long, currentSize: Long)
    }

    open class ListenerImpl :
        DownloadManagerUitlsListener {
        private var _onPrepare: (() -> Unit)? = null
        private var _onSuccess: ((path: String?) -> Unit)? = null
        private var _onFailed: ((throwable: Throwable?) -> Unit)? = null
        private var _onPercent: ((totalSize: Long, currentSize: Long) -> Unit)? = null

        override fun onPrepare() {
            _onPrepare?.invoke()
        }

        override fun onSuccess(path: String?) {
            _onSuccess?.invoke(path)
        }

        override fun onFailed(throwable: Throwable?) {
            _onFailed?.invoke(throwable)
        }

        override fun onDownloadPercent(totalSize: Long, currentSize: Long) {
            _onPercent?.invoke(totalSize, currentSize)
        }

        fun prepare(prepare: () -> Unit) {
            _onPrepare = prepare
        }

        fun success(success: (path: String?) -> Unit) {
            _onSuccess = success
        }

        fun fail(fail: (throwable: Throwable?) -> Unit) {
            _onFailed = fail
        }

        fun percent(percent: (totalSize: Long, currentSize: Long) -> Unit) {
            _onPercent = percent
        }
    }

    companion object {
        // ——————————————————————私有方法———————————————————————
        /**
         * 通过URL获取文件名
         *
         * @param url
         * @return
         */
        private fun getFileNameByUrl(url: String): String {
            var filename = url.substring(url.lastIndexOf("/") + 1)
            filename = filename.substring(
                0,
                if (filename.indexOf("?") == -1) filename.length else filename.indexOf("?")
            )
            return filename
        }
    }

}